package cclub.demo.service;

import cclub.demo.config.SecretConfig;
import cclub.demo.exception.SysException;
import cclub.demo.pojo.DO.userDO;
import cclub.demo.utils.jsonUtils;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

@Slf4j
@Service
@RequiredArgsConstructor
public class secretService {

    @NonNull
    private SecretConfig secretConfig;


    //生成签名
    public String getSign(Object objValue){
        String objContent = jsonUtils.getJson(objValue);
        try {
            PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(new BASE64Decoder().decodeBuffer(secretConfig.getPrivateKey()));
            KeyFactory keyF = KeyFactory.getInstance("RSA");
            PrivateKey priKey = keyF.generatePrivate(priPKCS8);
            Signature signature = Signature.getInstance("SHA1WithRSA");
            signature.initSign(priKey);
            signature.update(objContent.getBytes());
            byte[] signed = signature.sign();
            return new BASE64Encoder().encode(signed);
        }catch (Exception e){
            log.error("生成签名出现异常");
            e.printStackTrace();
        }
        return null;
    }

    //验签
    public boolean checkSign(String content,String sign){
        try {
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            byte[] encodedKey = new BASE64Decoder().decodeBuffer(secretConfig.getPublicKey());
            PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
            Signature signature = Signature.getInstance("SHA1WithRSA");
            signature.initVerify(pubKey);
            signature.update(content.getBytes());
            return signature.verify(new BASE64Decoder().decodeBuffer(sign));
        }catch (Exception e){
            log.error("验证签名出现异常");
            e.printStackTrace();
        }
        return false;
    }
    //使用JWT根据用户id和公钥生成生成token
    public String getToken(userDO userDO){
        return JWT.create().withAudience(userDO.getId().toString()).sign(Algorithm.HMAC256(secretConfig.getPrivateKey()));
    }

    //进行AES加密
    public String encryptAes(Object encryptObj) throws Exception{
        if(secretConfig.getAesKey() == null){
            log.error("加密数据时AES密钥为null");
            throw new SysException("加密数据时AES密钥为null");
        }
        ObjectMapper objectMapper = new ObjectMapper();
        byte[] raw = secretConfig.getAesKey().getBytes("utf-8");
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
        byte[] encrypted = cipher.doFinal(objectMapper.writeValueAsString(encryptObj).getBytes("utf-8"));
        return new BASE64Encoder().encode(encrypted);
    }

    //进行AES解密
    public String decryptAes(String decryptStr) throws Exception{
        if(secretConfig.getAesKey() == null){
            log.error("解密数据时AES密钥为null");
            throw new SysException("解密数据时AES密钥为null");
        }
        byte[] raw = secretConfig.getAesKey().getBytes("utf-8");
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, skeySpec);
        byte[] encrypted1 = new BASE64Decoder().decodeBuffer(decryptStr);
        try {
            byte[] original = cipher.doFinal(encrypted1);
            return new String(original,"utf-8");
        } catch (Exception e) {
            log.error("解密失败,解密数据={}",decryptStr);
            return null;
        }
    }
}
